#include "kdcdiscstructurewidget.h"

#include <kdclib.h>
#include <kdcnamespace.h>

#include <QVBoxLayout>
#include <QHBoxLayout>

#include <KLocale>
#include <KIcon>
#include <KFileDialog>
#include <KUrl>
#include <KConfig>
#include <KConfigGroup>
#include <KApplication>
#include <KDialog>
#include <KMessageBox>
#include <QAction>

#include <kdcdisc.h>
#include <kdcvts.h>
#include <kdcmovie.h>
#include <kdcmenu.h>
#include <KJob>
#include "discsettingswidget.h"
#include "movieorderwidget.h"

#include <interfaces/kdcjobsinterface.h>
extern KDCJobsInterface *gKDCJobsInterface;
#include <interfaces/kdcstatusbarinterface.h>
extern KDCStatusBarInterface *gKDCStatusBar;

KDCDiscStructureWidget::KDCDiscStructureWidget( QWidget *aParent ) : QWidget( aParent )
{
	pModel = new KDCDiscModel( this );
	pView = new DiscStructureTreeView( this );
	pView->setModel( pModel );
	pView->setContextMenuPolicy( Qt::ActionsContextMenu );
	pView->setSelectionMode( QAbstractItemView::ExtendedSelection );
	pToolBar = new KToolBar( this );
	pToolBar->setToolButtonStyle( Qt::ToolButtonIconOnly );
	
	QVBoxLayout *mainLayout = new QVBoxLayout( this );
	mainLayout->setMenuBar( pToolBar );
	mainLayout->addWidget( pView );
	mainLayout->setContentsMargins( 0, 0, 0, 0 );
	
	connect( pView->selectionModel(), SIGNAL( currentRowChanged( const QModelIndex &, const QModelIndex & ) ), this, SLOT( slotCurrentRowChanged( const QModelIndex &, const QModelIndex & ) ) );
}

KDCDiscStructureWidget::~KDCDiscStructureWidget()
{

}

KToolBar* KDCDiscStructureWidget::toolBar() const
{
	return pToolBar;
}

QTreeView* KDCDiscStructureWidget::view() const
{
	return pView;
}

void KDCDiscStructureWidget::addDiscTriggered( QAction *aAction )
{
	KDCDisc *disc = new KDCDisc( (KDC::DiscType)aAction->data().toInt() );
	pModel->addObject( disc );
	if ( disc->type() == KDC::DVD )
		pModel->addObject( disc, new KDCVTS );
}

void KDCDiscStructureWidget::addMenu()
{
	KDCDisc *disc = getDisc( pModel->objectFromIndex( pView->currentIndex() ) );
	if ( disc && !disc->menu() && disc->type() == KDC::DVD )
		pModel->addObject( disc, new KDCMenu );
}

void KDCDiscStructureWidget::addMovie()
{
	KDCObject *obj = pModel->objectFromIndex( pView->currentIndex() );
	if ( obj )
	{
		KConfig config("kdvdcreator");
		KConfigGroup general( &config, "General" );
		QString dir = general.readEntry( "LastMovieDir", QDir::homePath() );
		QString filter( "*.avi *.mpg *.mpeg *.vob *.rmvb *.mkv *.wmv *.asf *.mp4 *.rm *.flc *.mov|All Video Files" );
		QStringList files = KFileDialog::getOpenFileNames( KUrl( dir ), filter, this, i18n("Select one or more video files to open") );
		if ( !files.isEmpty() )
		{
			general.writeEntry( "LastMovieDir", QFileInfo( files.first() ).path() );
			general.config()->sync();
			openFiles( files );
		}
	}
}

void KDCDiscStructureWidget::openFiles( const QStringList& aFiles )
{
	KDCMovieMetaData *metaData;
	QString error;
	bool onlymovie = true;
	KDCObject *obj = pModel->objectFromIndex( pView->currentIndex() );
	KDCDisc *disc = getDisc( obj );
	KDCVTS *vts = NULL;
	if ( disc->type() == KDC::DVD )
		vts = getVTS( obj );
	KApplication::setOverrideCursor( QCursor( Qt::WaitCursor ) );
	foreach( QString aFile, aFiles )
	{
		error.clear();
		metaData = gKDCJobsInterface->getFileInfo( aFile, error );
		if ( !error.isEmpty() )
		{
			KApplication::restoreOverrideCursor();
			KMessageBox::error( this, i18n( "Error during open file") + " <i>" + aFile + "</i>", error );
			return;
		}
		else
			if ( metaData )
			{
				if ( !vts )
					pModel->addObject( disc, new KDCMovie( metaData ) );
				else
					pModel->addObject( vts, new KDCMovie( metaData ) );
			}
		else
			onlymovie = false;
	}
	KApplication::restoreOverrideCursor();
	gKDCStatusBar->showMessage( ( onlymovie ) ? i18n("All files loaded successfully.") : i18n("Some files could not be open."), KDC::Info );
}

void KDCDiscStructureWidget::addVTS()
{
	KDCDisc *disc = getDisc( pModel->objectFromIndex( pView->currentIndex() ) );
	if ( disc && disc->type() == KDC::DVD )
		pModel->addObject( disc, new KDCVTS );
}

void KDCDiscStructureWidget::deleteObject()
{
	KDCObject *obj = pModel->objectFromIndex( pView->currentIndex() );
	KDCDisc *disc = getDisc( obj );
	if ( obj && disc )
	{
		switch ( obj->object() )
		{
			case KDC::Disc: pModel->removeObject( disc, true ); break;
			case KDC::Menu: pModel->removeObject( disc, static_cast<KDCMenu*>( obj ), true ); break;
			case KDC::VTS:
			{
				pModel->removeObject( disc, static_cast<KDCVTS*>( obj ), true );
				if ( disc->vts().isEmpty() )
					pModel->addObject( disc, new KDCVTS );
				break;
			}
			case KDC::Movie:
			{
				if ( disc->type() == KDC::DVD )
					pModel->removeObject( getVTS( obj ), static_cast<KDCMovie*>( obj ), true );
				else
					pModel->removeObject( disc, static_cast<KDCMovie*>( obj ), true );
				break;
			}
		}
	}
}

void KDCDiscStructureWidget::splitMovie()
{
	KDCObject *obj = pModel->objectFromIndex( pView->currentIndex() );
	KDCDisc *disc = getDisc( obj );
	if ( obj && obj->object() == KDC::Movie )
	{
		KDCMovie *movie = static_cast<KDCMovie*>( obj );
		QList<KDCMovie*> movies = movie->subMovies();
		for ( int i=0; i<movies.size(); ++i )
		{
			movie->removeSubMovie( i );
			if ( disc->type() == KDC::DVD )
				pModel->addObject( getVTS( obj ), movies.at( i ) );
			else
				pModel->addObject( disc, movies.at( i ) );
		}
	}
}

void KDCDiscStructureWidget::joinMovie()
{
	QModelIndexList movies = pView->selectionModel()->selectedIndexes();
	if ( movies.size() < 2 )
		return;
	KDCObject *obj;
	KDCMovie *movie = NULL;
	int i;
	for ( i=0; i<movies.size(); ++i )
	{
		obj = pModel->objectFromIndex( movies.at( i ) );
		if ( obj && obj->object() == KDC::Movie )
		{
			movie = static_cast<KDCMovie*>( obj );
			movies.removeAt( i );
			break;
		}
	}
	if ( !movie )
		return;
	KDCDisc *disc;
	KDCMovie *tmp;
	for ( i=0; i<movies.size(); ++i )
	{
		obj = pModel->objectFromIndex( movies.at( i ) );
		if ( obj && obj->object() == KDC::Movie )
		{
			tmp = static_cast<KDCMovie*>( obj );
			disc = getDisc( obj );
			if ( disc->type() == KDC::DVD )
				pModel->removeObject( getVTS( obj ), tmp, false );
			else
				pModel->removeObject( disc, tmp, false );
			movie->addSubMovie( tmp );
		}
	}
}

void KDCDiscStructureWidget::orderMovie()
{
	KDCObject *obj = pModel->objectFromIndex( pView->currentIndex() );
	KDCDisc *disc = getDisc( obj );
	if ( obj && obj->object() == KDC::Movie )
	{
		KDCMovie *movie = static_cast<KDCMovie*>( obj );
		if ( movie->subMovies().size() == 0 )
			return;
		MovieOrderWidget *widget = new MovieOrderWidget( this );
		widget->setMovie( movie );
		KDialog dlg( this );
		dlg.setButtons( KDialog::Ok | KDialog::Cancel );
		dlg.setMainWidget( widget );
		if ( dlg.exec() )
		{
			KDCVTS *vts = getVTS( obj );
			if ( disc->type() == KDC::DVD )
			{
				pModel->removeObject( vts, movie, false );
				widget->save();
				pModel->addObject( vts, widget->newMovie() );
			}
			else
			{
				pModel->removeObject( disc, movie, false );
				widget->save();
				pModel->addObject( disc, widget->newMovie() );
			}
		}
	}
}

void KDCDiscStructureWidget::slotCurrentRowChanged( const QModelIndex &aCurrent, const QModelIndex &aPrevious )
{
	KDCObject *obj = pModel->objectFromIndex( aCurrent );
	emit currentObjectChanged( obj );
	if ( getDisc( obj ) != getDisc( pModel->objectFromIndex( aPrevious ) ) );
		emit discChanged( getDisc( obj ) );
}

void KDCDiscStructureWidget::setDiscSettings()
{
	KDCDisc *disc = getDisc( pModel->objectFromIndex( pView->currentIndex() ) );
	DiscSettingsWidget *widget = new DiscSettingsWidget( this );
	widget->setSettings( disc->settings() );
	KDialog dlg( this );
	dlg.setButtons( KDialog::Ok | KDialog::Cancel );
	dlg.setMainWidget( widget );
	if ( dlg.exec() )
	{
		widget->save();
		emit discChanged( disc );
		if ( gKDCStatusBar )
			gKDCStatusBar->showMessage( i18n("Disc settings changed."), KDC::Info );
	}
}
